local EV = require "packages/evolution/EV"
local U = require "packages/utility/utility"

local desc_role = [[
  # 萌战身份模式简介
  ___
  （一）身份改动及身份“明置”相关
  
  1.主公——“主教”（基础胜利条件同三国杀主公） 
  
  萌战没有常备主公，改为“主教”备选角色数增加三名。当“主教”选择角色后，若游戏人数为6或8，其选择一项“恩典”并获得之，然后其余玩家选择角色。
  
  恩典及其效果分别为：
  
  睿智：游戏开始时，你观看所有角色的身份牌。准备阶段，你可明置一名角色的身份牌。当你成为“骑士”使用【杀】的目标后，若你的手牌数不大于手牌上限，你摸一张牌。
  
  威光：游戏开始时，你摸一张牌并将此牌置于恩典牌上。准备阶段，你选择是否用一张牌替换“威光”牌。其他角色使用或打出与“威光”牌花色相同的牌时，若其体力值不大于你，你可令其弃置一张牌。
  
  神武：游戏开始时，你将所有其他角色的各一张牌洗入牌堆。准备阶段，你可摸一张牌，与一名其他角色拼点；若你赢，则你获得其拼点的牌，且当你于本回合内造成伤害时，你令此伤害+1。
  
  2.主教于选择角色前明置身份牌，其身份牌不可被暗置。一名角色的回合开始时，若其身份不为主教，其可明置身份牌，然后触发以下效果：
  
  （1）忠臣——“神官”（胜利条件：主教获得胜利）
 
  其选择一项：1.获得“圣盾”；2.弃置场上的一张武器牌或延时魔法牌。
  
  圣盾：其他角色使用牌指定目标后，若此牌为其于当前回合内使用的第X张牌（X为已明置的“神官”数），你可令此牌对“主教”无效。
  
  （2）反贼——“骑士/先知”（基础胜利条件同三国杀反贼）
  
  其选择一项：1.若没有角色成为过“先知”，其将身份改为“先知”，然后若其没有“占星”，其获得“占星”；2.令一名手牌数小于其的“骑士”或“先知”摸一张牌。
  
  占星：一名角色的回合开始时，若其为己方角色，你可观看牌堆顶的四张牌并改变其中任意数量的牌的顺序；若此时不在你的回合内，你选择一项：1.弃置X张牌；2.失去此技能（X为你于本轮内发动“占星”的次数）。
  
  （3）内奸——“游侠”（基础胜利条件同三国杀内奸） 
  
  若游戏人数不小于6，其观看“天命”牌堆（见下方）中的X张牌，将其中的一张牌扣置于角色牌旁（X为游戏人数的一半减轮次数）。
  
  秩序：一名角色的回合结束后，若所有角色的手牌数形成等差数列（公差至少为1），你胜利。
  
  善良：每轮结束时，若本轮没有角色受到过伤害，你胜利。
  
  中立：每轮开始时，或回合结束后，若角色数等于轮次数，你胜利。
  
  邪恶：其他角色死亡时，若你杀死过两名角色，你胜利。
  
  混乱：回合结束后，若所有角色的体力值均不相同，你胜利。
  
  注：当一名角色完成“天命”后，若其不为主教，其获胜，死亡。游戏继续进行。换言之，“天命”与其余胜利条件不冲突。
  
  当一名角色死亡后，若其有“天命”牌，其将“天命”牌洗入“天命”牌堆。
  
  （二）身份奖惩改动
  
  1.当“主教”杀死“神官”时，其获得“神官”区域里的所有牌，然后失去“恩典”。
  
  2.当一名角色杀死“先知”时，其摸三张牌，令所有“骑士”各弃置一张牌。
  
  3.当一名角色杀死“骑士”时，其摸两张牌。  
]]

local ev_role_getLogic = function()
  local ev_role_logic = GameLogic:subclass("ev_role_logic")
  function ev_role_logic:run()
    self.room.settings.enableDeputy = false
    GameLogic.run(self)
  end

  function ev_role_logic:initialize(room)
    GameLogic.initialize(self, room)
    self.role_table = {
      nil,
      { "lord", "rebel"},
      { "lord", "rebel", "renegade"},
      { "lord", "rebel", "rebel", "renegade"},
      { "lord", "loyalist", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "rebel", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "loyalist", "rebel", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "loyalist", "rebel", "rebel", "rebel", "rebel", "renegade" },
    }
  end

  function ev_role_logic:chooseGenerals()
    local room = self.room---@type Room
    local generalNum = room.settings.generalNum
    local lord = room:getLord()
    if not lord then
      local temp = room.players[1]
      temp.role = "lord"
      lord = temp
    end
    lord.role_shown = true
    room.current = lord

    local lord_general_num = 3
    local lord_generals = room:getNGenerals(generalNum + lord_general_num)
    if #room.general_pile < (#room.players - 1) * generalNum then
      room:gameOver("")
    end

    local lord_general = room:askForGeneral(lord, lord_generals, 1)---@type string
    table.removeOne(lord_generals, lord_general)
    room:returnToGeneralPile(lord_generals)
    room:findGeneral(lord_general)
    room:prepareGeneral(lord, lord_general, true)
    room:broadcastProperty(lord, "general")

    local canAttachSkill = function(player, skillName)
      local skill = Fk.skills[skillName]
      if not skill then
        fk.qCritical("Skill: "..skillName.." doesn't exist!")
        return false
      end
      if skill.lordSkill and (player.role ~= "lord" or #room.players < 5) then
        return false
      end

      if #skill.attachedKingdom > 0 and not table.contains(skill.attachedKingdom, player.kingdom) then
        return false
      end

      return true
    end
    local lord_skills = {}
    for _, s in ipairs(Fk.generals[lord.general].skills) do
      if canAttachSkill(lord, s.name) then
        table.insertIfNeed(lord_skills, s.name)
      end
    end
    for _, sname in ipairs(Fk.generals[lord.general].other_skills) do
      if canAttachSkill(lord, sname) then
        table.insertIfNeed(lord_skills, sname)
      end
    end
    for _, skill in ipairs(lord_skills) do
      room:doBroadcastNotify("AddSkill", json.encode{
        lord.id,
        skill
      })
    end

    local nonlord = room:getOtherPlayers(lord, true)
    local generals = room:getNGenerals(#nonlord * generalNum)
    if #generals < #nonlord * generalNum then
      room:gameOver("")
    end
    table.shuffle(generals)
    for i, p in ipairs(nonlord) do
      local arg = table.slice(generals, (i - 1) * generalNum + 1, i * generalNum + 1)
      p.request_data = json.encode{ arg, 1 }
      p.default_reply = table.random(arg, 1)
    end

    room:notifyMoveFocus(nonlord, "AskForGeneral")
    room:doBroadcastRequest("AskForGeneral", nonlord)

    local selected = {}
    for _, p in ipairs(nonlord) do
      local general
      if p.general == "" and p.reply_ready then
        local general_ret = json.decode(p.client_reply)
        general = general_ret[1]
      else
        general = p.default_reply[1]
      end
      table.insert(selected, general)
      room:findGeneral(general)
      room:prepareGeneral(p, general)
      p.default_reply = ""
    end
    generals = table.filter(generals, function(g) return not table.contains(selected, g) end)
    room:returnToGeneralPile(generals)
    room:setTag("SkipNormalDeathProcess", true)--重要
  end

  function ev_role_logic:broadcastGeneral()
    local room = self.room
    local players = room.players
    for _, p in ipairs(players) do
      assert(p.general ~= "")
      local general = Fk.generals[p.general]
      p.maxHp = p:getGeneralMaxHp()
      p.hp = general.hp
      p.shield = math.min(general.shield, 5)
      -- TODO: setup AI here
      if p.role == "lord" and p.general ~= "hiddenone" and #room.players >= 5 then
        p.maxHp = p.maxHp + 1
        p.hp = p.hp + 1
      end
      room:broadcastProperty(p, "general")
      room:broadcastProperty(p, "kingdom")
      room:broadcastProperty(p, "maxHp")
      room:broadcastProperty(p, "hp")
      room:broadcastProperty(p, "shield")
    end
  end

  function ev_role_logic:attachSkillToPlayers()
    local room = self.room
    local addRoleModSkills = function(player, skillName)
      local skill = Fk.skills[skillName]
      if not skill then
        fk.qCritical("Skill: "..skillName.." doesn't exist!")
        return
      end
      if skill.lordSkill then
        return
      end
      if #skill.attachedKingdom > 0 and not table.contains(skill.attachedKingdom, player.kingdom) then
        return
      end
      room:handleAddLoseSkills(player, skillName, nil, false)
    end
    for _, p in ipairs(room.alive_players) do
      for _, s in ipairs(Fk.generals[p.general]:getSkillNameList(false)) do
        addRoleModSkills(p, s)
      end
    end
    local lord = room:getLord()
    if lord and #room.players >= 6 and #room.players ~= 7 then
      local endian = room:askForChoice(lord, {"evr_ruizhi&", "evr_weiguang&", "evr_shenwu&"}, "endian", "#endian-get", true)
      room:setBanner("@[:]endian", endian)
      room:handleAddLoseSkills(lord, endian, nil, false)
    end
  end
  return ev_role_logic
end

local function rewardAndPunish(killer, victim, room)
  if killer.dead then return end
  local prophet = room:getTag("prophet")
  if killer.role == "renegade" then
    room:addPlayerMark(killer, "evil-count")
  end
  if killer.role == "lord" and victim.role == "loyalist" then
    --killer:throwAllCards("he")
    --local cards_id = victim:getCardIds("he")
    --room:obtainCard(killer.id, cards_id, false, fk.ReasonPrey)
    local endian = room:getBanner("@[:]endian")
    room:handleAddLoseSkills(killer, "-"..endian, nil, false)
  end
  if victim.role == "rebel" then
    if victim.id == prophet then--击杀先知
      killer:drawCards(3, "kill")
      for _, p in ipairs(room.alive_players) do
        if p.role == "rebel" and p.role_shown then
          room:askForDiscard(p, 1, 1, true, "kill", false)
        end
      end
    else
      killer:drawCards(2, "kill")
    end
  end
end

local function isArithmeticProgression(t)--GPT
  if #t < 2 then return false end
  table.sort(t)
  local commonDiff = t[2] - t[1]
  for i = 2, #t - 1 do
    if t[i + 1] - t[i] ~= commonDiff then
        return false
    end
  end
  return true
end

local function areElementsUnique(t)
  if #t < 2 then return false end
  local seen = {}
  for _, v in ipairs(t) do
      if seen[v] then
          return false
      end
      seen[v] = true
  end
  return true
end

local ev__destiny = fk.CreateTriggerSkill{
  name = "#ev__destiny&",
  priority = 0.01,
  mute = true,
  events = {fk.TurnEnd, fk.RoundEnd, fk.RoundStart, fk.Deathed},
  can_trigger = function(self, event, target, player, data)
    local room = player.room
    if #U.getPrivateMark(player, "destiny") == 0 or not player:hasSkill(self.name) then return end
    if event == fk.TurnEnd then
      if U.getPrivateMark(player, "destiny")[1] == "ev_order" then--秩序
        local handnums = table.map(room.alive_players, function (p) return p:getHandcardNum() end)
        return isArithmeticProgression(handnums)
      elseif target == player then--混乱
        if U.getPrivateMark(player, "destiny")[1] == "ev_chaos" then
          local hps = table.map(room.alive_players, function (p) return p.hp end)
          return areElementsUnique(hps)
        elseif U.getPrivateMark(player, "destiny")[1] == "ev_neutral" then
          return #room.alive_players == room:getTag("RoundCount")
        end
      end
    elseif event == fk.RoundEnd then
      if U.getPrivateMark(player, "destiny")[1] == "ev_kindness" then
        return #player.room.logic:getEventsOfScope(GameEvent.ChangeHp, 1, function (e)
          local damage = e.data[5]
          if damage and damage.damage > 0 then
            return true
          end
        end, Player.HistoryRound) == 0
      end
    elseif event == fk.RoundStart then
      if U.getPrivateMark(player, "destiny")[1] == "ev_neutral" then
        return #room.alive_players == room:getTag("RoundCount")
      end
    elseif event == fk.Deathed then
      if U.getPrivateMark(player, "destiny")[1] == "ev_evil" then
        return player:getMark("evil-count") >= 2
      end
    end
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    player.room:setBanner("@[:]destiny", U.getPrivateMark(player, "destiny")[1])
    player.room:killPlayer({who = player.id,})
    --player.room:gameOver("renegade")
  end,
}

Fk:addSkill(ev__destiny)

local ev_role_rule = fk.CreateTriggerSkill{
  name = "#ev_role_rule",
  priority = 10,
  mute = true,
  events = {fk.Death, fk.Deathed, fk.TurnStart},
  --- FIXME:执行奖惩时机应为fk.BuryVictim，需要SkipGameRule逻辑大改
  can_trigger = function(self, event, target, player, data)
    if event == fk.Death then
      return target == player and player.role == "loyalist" and data.damage and data.damage.from
       and data.damage.from.role == "lord" and not player:isNude()
    elseif event == fk.Deathed then
      return target == player and player.rest == 0
    elseif event == fk.TurnStart then
      return target == player and not player.role_shown
    end
  end,
  on_cost = function(self, event, target, player, data)
    if event == fk.TurnStart then
      return player.room:askForSkillInvoke(player, self.name, data, "#ev_show_role")
    else
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.Death then
      local cards_id = player:getCardIds("he")
      room:obtainCard(data.damage.from.id, cards_id, false, fk.ReasonPrey)
    elseif event == fk.Deathed then
      local damage = data.damage
      if damage and damage.from then
        local killer = damage.from
        rewardAndPunish(killer, player, room)
      end
    elseif event == fk.TurnStart then
      room:setPlayerProperty(player, "role_shown", true)
      room:broadcastProperty(player, "role")
      room.logic:trigger("fk.RoleShown", player, {from = player.id})
      if #room.players < 5 then return end
      if player.role == "loyalist" then
        --local id = EV.chooseCardonBoard(room, player, self.name, "#ev_shenguan-choose")
        local cards = {}
        for _, p in ipairs(room.alive_players) do
          for _, id in ipairs(p:getCardIds("ej")) do
            if Fk:getCardById(id).sub_type == Card.SubtypeWeapon or Fk:getCardById(id).sub_type == Card.SubtypeDelayedTrick then
              table.insert(cards, id)
            end
          end
        end
        local card_ids = {}
        if #cards > 0 then
          local ids, _ = U.askforChooseCardsAndChoice(player, cards, {"OK"}, self.name,
          "#ev_shenguan-choose", {"cancel"}, 1, 1)
          if #ids > 0 then
            table.insert(card_ids, ids[1])
          end
        end
        if #card_ids > 0 and (Fk:getCardById(card_ids[1]).sub_type == Card.SubtypeWeapon or Fk:getCardById(card_ids[1]).sub_type == Card.SubtypeDelayedTrick) then
          room:moveCardTo(card_ids[1], Card.DiscardPile, nil, fk.ReasonDiscard, self.name, "", true)
        else
          room:handleAddLoseSkills(player, "ev__shengdun&")
        end
      elseif player.role == "rebel" then
        local targets = table.map(table.filter(room.alive_players,
        function(p) return p:getHandcardNum() < player:getHandcardNum() and p.role_shown and p.role == "rebel" end), Util.IdMapper)
        local to = room:askForChoosePlayers(player, targets, 1, 1, "#knight-choose", self.name, true)
        if #to > 0 then
          room:getPlayerById(to[1]):drawCards(1, self.name)
        elseif not room:getTag("prophet") or room:getTag("prophet") == "" then
          room:setTag("prophet", player.id)
          room:addPlayerMark(player, "@@prophet")
          room:handleAddLoseSkills(player, "ev__zhanxing&")
        end
      elseif player.role == "renegade" and #room.players > 5 then
        local destiny = room:getTag("destiny")
        if not destiny or destiny == "" then destiny = {"ev_order", "ev_kindness", "ev_neutral", "ev_evil", "ev_chaos"} end
        local n = #room.players // 2 - room:getTag("RoundCount")
        if n > 0 then
          local choice = room:askForChoice(player, table.random(destiny, n), "destiny", "#destiny-get", true)
          U.setPrivateMark(player, "destiny", {choice})
          table.removeOne(destiny, choice)
          room:setTag("destiny", destiny)
          room:handleAddLoseSkills(player, "#ev__destiny&", self.name, false)
        end
      end
    end
  end,
}

Fk:addSkill(ev_role_rule)


local ev_ruizhi = fk.CreateTriggerSkill{
  name = "evr_ruizhi&",
  anim_type = "defensive",
  events = {fk.TargetConfirmed, fk.GameStart, fk.EventPhaseStart},
  can_trigger = function(self, event, target, player, data)
    if event == fk.TargetConfirmed then
      return target == player and player:hasSkill(self.name) and data.firstTarget and data.card.trueName == "slash"
      and player.room:getPlayerById(data.from).role == "rebel" and player.room:getPlayerById(data.from).role_shown
      and player.room:getPlayerById(data.from):getMark("@@prophet") == 0 and player:getHandcardNum() <= player:getMaxCards()
    elseif event == fk.EventPhaseStart then
      return player:hasSkill(self.name) and target == player and player.phase == Player.Start
    else
      return player:hasSkill(self.name)
    end
  end,
  on_cost = function(self, event, target, player, data)
    if event == fk.TargetConfirmed then
      return player.room:askForSkillInvoke(player, self.name)
    elseif event == fk.EventPhaseStart then
      local targets = table.map(table.filter(player.room:getOtherPlayers(player), function(p) return not p.role_shown end), Util.IdMapper)
      local to = player.room:askForChoosePlayers(player, targets, 1, 1, "#ev_ruizhi-target", self.name, true)
      if #to > 0 then
        self.cost_data = to[1]
        player.room:doIndicate(player.id, {to[1]})
        return true
      end
    else
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.TargetConfirmed then
      player:drawCards(1, self.name)
    elseif event == fk.EventPhaseStart then
      local to = room:getPlayerById(self.cost_data)
      room:setPlayerProperty(to, "role_shown", true)
    else
      room:handleAddLoseSkills(player, '#shown_role', nil, true, false)
      for _, p in ipairs(room:getOtherPlayers(player)) do
        room:notifyProperty(player, p, "role")
      end
    end
  end,
}

local shown_role = fk.CreateVisibilitySkill{
  name = '#shown_role',
  frequency = Skill.Compulsory,
  role_visible = function(self, player, target)
    return player:hasSkill(self) and player ~= target
  end
}

Fk:addSkill(shown_role)
Fk:addSkill(ev_ruizhi)

local ev_shenwu = fk.CreateTriggerSkill{
  name = "evr_shenwu&",
  anim_type = "offensive",
  events = {fk.EventPhaseStart, fk.DamageCaused, fk.GameStart},
  can_trigger = function(self, event, target, player, data)
    if event == fk.EventPhaseStart then
      return target == player and player:hasSkill(self.name) and player.phase == Player.Start-- and not player:isKongcheng()
    elseif event == fk.DamageCaused then
      return target == player and player:getMark("@@ev_shenwu-turn") > 0--player:hasSkill(self.name)
    elseif event == fk.GameStart then
      return player:hasSkill(self.name)
    end
  end,
  on_cost = function(self, event, target, player, data)
    if event == fk.EventPhaseStart then
      return player.room:askForSkillInvoke(player, self.name)
    else
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.EventPhaseStart then
      player:drawCards(1, self.name)
      local to = room:askForChoosePlayers(player, table.map(table.filter(room:getOtherPlayers(player), function(p)
        return player:canPindian(p) end), Util.IdMapper),
        1, 1, "#ev_shenwu-choose", self.name, false)
      if #to > 0 then
        local pindian = player:pindian(table.map(to, Util.Id2PlayerMapper), self.name)
        if pindian.results[to[1]].winner == player then
          room:setPlayerMark(player, "@@ev_shenwu-turn", 1)
        else
          --room:moveCardTo(pindian.results[to[1]].toCard, Card.PlayerHand, player, fk.ReasonJustMove, self.name, "", true, player.id)
        end
      end
    elseif event == fk.DamageCaused then
      data.damage = data.damage + 1
    elseif event == fk.GameStart then
      for _, p in ipairs(room:getOtherPlayers(player)) do
        local card = table.random(p:getCardIds(Player.Hand), 1)
        if #card > 0 then
          room:moveCards({
            ids = card,
            from = p.id,
            fromArea = Card.PlayerHand,
            toArea = Card.DrawPile,
            moveReason = fk.ReasonJustMove,
            skillName = self.name,
            drawPilePosition = math.random(1, #room.draw_pile),
          })
        end
      end
    end
  end,
}

Fk:addSkill(ev_shenwu)

local ev_weiguang = fk.CreateTriggerSkill{
  name = "evr_weiguang&",
  derived_piles = "#ev_weiguang",
  anim_type = "control",
  events = {fk.GameStart, fk.EventPhaseStart, fk.CardUsing, fk.CardResponding},
  can_trigger = function(self, event, target, player, data)
    if event == fk.GameStart then
      return player:hasSkill(self.name)
    elseif event == fk.EventPhaseStart then
      return target == player and player:hasSkill(self.name) and player.phase == Player.Start and #player:getPile("#ev_weiguang") > 0
    elseif event == fk.CardUsing or event == fk.CardResponding then
      if player:hasSkill(self.name) and #player:getPile("#ev_weiguang") > 0 then
        return data.card.suit == Fk:getCardById(player:getPile("#ev_weiguang")[1]).suit and target.hp <= player.hp and
        player ~= target and not target:isNude()
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    if event == fk.EventPhaseStart then
      return true
    elseif event == fk.GameStart then
      return true
    elseif event == fk.CardUsing or event == fk.CardResponding then
      return player.room:askForSkillInvoke(player, self.name, data, "#evr_weiguang-invoke::"..target.id)
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.EventPhaseStart then
      local cids = U.askForExchange(player, self.name, player.general, player:getPile("#ev_weiguang"), player:getCardIds("he"), "#ev_weiguang-exchange", 1, true)
      if #cids > 0 then
        local cards = table.filter(cids, function (id)
          return table.contains(player:getCardIds("he"), id)
        end)
        local weiguang = table.filter(cids, function (id)
          return not table.contains(player:getCardIds("he"), id)
        end)
        U.swapCardsWithPile(player, cards, weiguang, self.name, "#ev_weiguang", true, player.id)
        room:setPlayerMark(player, "@[weiguang_show]", player:getPile("#ev_weiguang"))
      end
    elseif event == fk.GameStart then
      --local card = room:getNCards(1)
      local card = player:drawCards(1, self.name)
      player:addToPile("#ev_weiguang", card[1], true, self.name)
      room:setPlayerMark(player, "@[weiguang_show]", player:getPile("#ev_weiguang"))
    elseif event == fk.CardUsing or event == fk.CardResponding then
      room:askForDiscard(target, 1, 1, true, self.name, false)
    end
  end,
}

Fk:addSkill(ev_weiguang)

local ev__zhanxing = fk.CreateTriggerSkill{
  name = "ev__zhanxing&",
  anim_type = "control",
  events = {fk.TurnStart},
  can_trigger = function(self, event, target, player, data)
    return EV.isFriend(player, target) and player:hasSkill(self.name)
  end,
  on_cost = function(self, event, target, player, data)
    local n = player:usedSkillTimes(self.name, Player.HistoryRound)
    return player.room:askForSkillInvoke(player, self.name, nil, "#ev__zhanxing-invoke:::"..n)
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local cards = room:getNCards(4)
    --room:moveCardTo(cards, Card.Processing, nil, fk.ReasonJustMove, self.name)
    room.logic:trigger("fk.ZhanXing", player, {ids = cards})
    room:askForGuanxing(player, cards, {#cards, #cards}, {0, 0})
    if player.phase == Player.NotActive then
      local n = player:usedSkillTimes(self.name, Player.HistoryRound)
      local discard = room:askForDiscard(player, n, n, true, self.name, true, ".", "#ev__zhanxing:::"..n)
      if #discard == 0 then
        room:handleAddLoseSkills(player, "-ev__zhanxing&")
      end
    end
  end,
}
Fk:addSkill(ev__zhanxing)

local ev__shengdun = fk.CreateTriggerSkill{
  name = "ev__shengdun&",
  events = {fk.TargetSpecified},
  anim_type = "defensive",
  can_trigger = function(self, event, target, player, data)
    if target ~= player and player:hasSkill(self) and table.contains(AimGroup:getAllTargets(data.tos), player.room:getLord().id)
    and data.firstTarget then
      local loyalists = #table.filter(player.room.alive_players, function(p) return p.role == "loyalist" and p.role_shown end)
      return #player.room.logic:getEventsOfScope(GameEvent.UseCard, 5, function(e)
        local use = e.data[1]
        return use.from == target.id end, Player.HistoryTurn) == loyalists
    end
  end,
  on_use = function(self, event, target, player, data)
    if data.card.type ~= Card.TypeEquip then
      EV.nullifiedCard(data, data.card, player.room:getLord())
    end
  end,

  refresh_events = {fk.TurnStart, fk.CardUsing},
  can_refresh = function(self, event, target, player, data)
    if event == fk.TurnStart then
      return player:hasSkill(self) and target ~= player and player.room:getLord()
    else
      if target ~= player and player:hasSkill(self) then
        local loyalists = #table.filter(player.room.players, function(p) return p.role == "loyalist" and p.role_shown end)
        return #player.room.logic:getEventsOfScope(GameEvent.UseCard, 5, function(e)
          local use = e.data[1]
          return use.from == target.id end, Player.HistoryTurn) == loyalists
      end
    end
  end,
  on_refresh = function(self, event, target, player, data)
    if event == fk.TurnStart then
      player.room:addPlayerMark(player.room:getLord(), "@@ev__shengdun-turn")
    else
      player.room:setPlayerMark(player.room:getLord(), "@@ev__shengdun-turn", 0)
    end
  end,
}
Fk:addSkill(ev__shengdun)

local role_mode = fk.CreateGameMode{
  name = "ev_role_mode", -- just to let it at the top of list
  minPlayer = 2,
  maxPlayer = 8,
  rule = ev_role_rule,
  logic = ev_role_getLogic,
  surrender_func = Fk.game_modes["aaa_role_mode"].surrenderFunc,
  winner_getter = function(self, victim)
    local room = victim.room
    if not victim.surrendered and victim.rest > 0 then
      return ""
    end
    local winner = ""
    local alive = table.filter(room.players, function(p)
      return not p.surrendered and not (p.dead and p.rest == 0)
    end)
    local destiny = room:getBanner("@[:]destiny") and room:getBanner("@[:]destiny") ~= ""
    if victim.role == "lord" then
      if #alive == 1 and alive[1].role == "renegade" then
        winner = "renegade"
      else
        if destiny then
          winner = "rebel+renegade"
        else
          winner = "rebel"
        end
      end
    elseif victim.role ~= "loyalist" then
      local lord_win = true
      for _, p in ipairs(alive) do
        if p.role == "rebel" or p.role == "renegade" then
          lord_win = false
          break
        end
      end
      if lord_win then
        if destiny then
          winner = "lord+loyalist+renegade"
        else
          winner = "lord+loyalist"
        end
      end
    end
  
    return winner
  end,
}

Fk:loadTranslationTable{
  ["ev_role_mode"] = "萌战身份局",
  [":ev_role_mode"] = desc_role,
  ["#ev_role_rule"] = "身份规则",
  --["#ev_role_mode"] = "",
  ["endian"] = "恩典",
  ["#endian-get"] = "请选择一项恩典获得之",
  ["#ev_show_role"] = "你可以明置身份牌",
  ["#ev_shenguan-choose"] = "你可以选择场上一张武器牌或延时锦囊牌弃置，否则你获得“圣盾”",
  ["#knight-choose"] = "你可令一名手牌数小于你的队友摸一张牌，否则若没有角色成为过先知，你成为先知",
  ["@@prophet"] = "先知",
  ["destiny"] = "天命",
  ["#destiny-get"] = "请选择你的天命牌",
  ["lord+loyalist+renegade"] = "神谕，中立",
  ["rebel+renegade"] = "天启，中立",

  ["evr_ruizhi&"] = "睿智",
  [":evr_ruizhi&"] = "游戏开始时，你观看所有角色的身份牌。准备阶段，你可明置一名角色的身份牌。当你成为“骑士”使用【杀】的目标后，若你的手牌数不大于手牌上限，你摸一张牌。",
  ["#ev_ruizhi-target"] = "睿智：你可明置一名角色的身份牌",

  ["evr_weiguang&"] = "威光",
  [":evr_weiguang&"] = "游戏开始时，你摸一张牌并将此牌置于恩典牌上。准备阶段，你选择是否用一张牌替换“威光”牌。其他角色使用或打出与“威光”牌花色相同的牌时，若其体力值不大于你，你可令其弃置一张牌。",
  ["#evr_weiguang-invoke"] = "威光：你可以令%dest弃置一张牌",
  
  ["evr_shenwu&"] = "神武",
  [":evr_shenwu&"] = "游戏开始时，你将所有其他角色的各一张牌洗入牌堆。准备阶段，你可摸一张牌，与一名其他角色拼点；若你赢，当你于本回合内造成伤害时，你令此伤害+1。",--，若你没赢，你获得其拼点的牌
  ["ev__shengdun&"] = "圣盾",
  [":ev__shengdun&"] = "其他角色使用牌指定目标后，若此牌为其于当前回合内使用的第X张牌（X为已明置的忠臣数），你可令此牌对主公无效。",
  ["@@ev__shengdun-turn"] = "<b><font color=\"#FFD700\">圣盾</font></b>",

  ["ev__zhanxing&"] = "占星",
  ["#ev__zhanxing-invoke"] = "你可发动占星，此轮已发动过%arg次",
  ["#ev__zhanxing"] = "请弃置%arg张牌，否则失去【占星】",
  [":ev__zhanxing&"] = "一名角色的回合开始时，若其为己方角色，你可观看牌堆顶的四张牌并改变其中任意数量的牌的顺序；若此时不在你的回合内，你选择一项：1.弃置X张牌；2.失去此技能（X为你于本轮内发动“占星”的次数）。",

  ["@[private]destiny"] = "天命",
  ["ev_order"] = "秩序",
  [":ev_order"] = "一名角色的回合结束后，若所有角色的手牌数形成等差数列（公差至少为1），你胜利。",
  ["ev_kindness"] = "善良",
  [":ev_kindness"] = "每轮结束时，若本轮没有角色受到过伤害，你胜利。",
  ["ev_neutral"] = "中立",
  [":ev_neutral"] = "每轮开始时，或回合结束后，若角色数等于轮次数，你胜利。",
  ["ev_evil"] = "邪恶",
  [":ev_evil"] = "其他角色死亡时，若你杀死过两名角色，你胜利。",
  ["ev_chaos"] = "混乱",
  [":ev_chaos"] = "回合结束后，若所有角色的体力值均不相同，你胜利。",
  ["@[:]destiny"] = "完成天命",
}

return role_mode
